home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / telecomm / sticpsrc.lzh / SOURCE.ARC / TCPIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-18  |  22.8 KB  |  856 lines

  1. /* Process incoming TCP segments. Page number references are to ARPA RFC-793,
  2.  * the TCP specification.
  3.  */
  4.  
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "icmp.h"
  12. #include "iface.h"
  13. #include "ip.h"
  14.  
  15. struct tcp_stat tcp_stat;
  16.  
  17. /* This function is called from IP with the IP header in machine byte order,
  18.  * along with a mbuf chain pointing to the TCP header.
  19.  */
  20. void
  21. tcp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  22. struct mbuf *bp;    /* Data field, if any */
  23. char protocol;        /* Should always be TCP_PTCL */
  24. int32 source;        /* Remote IP address */
  25. int32 dest;        /* Our IP address */
  26. char tos;        /* Type of Service */
  27. int16 length;        /* Length of data field */
  28. char rxbroadcast;    /* Incoming broadcast - discard if true */
  29. {
  30.     void reset(),update();
  31.     void proc_syn(),send_syn(),add_reseq(),get_reseq(),unlink_tcb();
  32.  
  33.     register struct tcb *tcb;    /* TCP Protocol control block */
  34.     struct tcp seg;            /* Local copy of segment header */
  35.     struct connection conn;        /* Local copy of addresses */
  36.     struct pseudo_header ph;    /* Pseudo-header for checksumming */
  37.     int hdrlen;            /* Length of TCP header */
  38.  
  39.     if(bp == NULLBUF)
  40.         return;
  41.  
  42.     if(rxbroadcast){
  43.         /* Any TCP packet arriving as a broadcast is
  44.          * to be completely IGNORED!!
  45.          */
  46.         tcp_stat.bdcsts++;
  47.         free_p(bp);
  48.         return;
  49.     }
  50.     ph.source = source;
  51.     ph.dest = dest;
  52.     ph.protocol = protocol;
  53.     ph.length = length;
  54.     if(cksum(&ph,bp,length) != 0){
  55.         /* Checksum failed, ignore segment completely */
  56.         tcp_stat.checksum++;
  57.         free_p(bp);
  58.         return;
  59.     }
  60.     /* Form local copy of TCP header in host byte order */
  61.     if((hdrlen = ntohtcp(&seg,&bp)) < 0){
  62.         /* TCP header is too small */
  63.         tcp_stat.runt++;
  64.         free_p(bp);
  65.         return;
  66.     }
  67.     length -= hdrlen;
  68.  
  69.     /* Fill in connection structure and find TCB */
  70.     conn.local.address = dest;
  71.     conn.local.port = seg.dest;
  72.     conn.remote.address = source;
  73.     conn.remote.port = seg.source;
  74.  
  75.     if((tcb = lookup_tcb(&conn)) == NULLTCB){
  76.         struct tcb *ntcb;
  77.         void link_tcb();
  78.  
  79.         /* Check that this segment carries a SYN, and that
  80.          * there's a LISTEN on this socket with
  81.          * unspecified source address and port
  82.          */
  83.         conn.remote.address = 0;
  84.         conn.remote.port = 0;
  85.         if(!(seg.flags & SYN) || (tcb = lookup_tcb(&conn)) == NULLTCB){
  86.             /* No unspecified LISTEN either, so reject */
  87.             free_p(bp);
  88.             reset(source,dest,tos,length,&seg);
  89.             return;
  90.         }
  91.         /* We've found an server listen socket, so clone the TCB */
  92.         if(tcb->flags & CLONE){
  93.             if((ntcb = (struct tcb *)malloc(sizeof (struct tcb))) == NULLTCB){
  94.                 free_p(bp);
  95.                 /* This may fail, but we should at least try */
  96.                 reset(source,dest,tos,length,&seg);
  97.                 return;
  98.             }
  99.             ASSIGN(*ntcb,*tcb);
  100.             tcb = ntcb;
  101.             tcb->timer.arg = (char *)tcb;
  102.             tcb->timeout.arg = (char *)tcb;
  103.         } else
  104.             unlink_tcb(tcb);    /* It'll be put back on later */
  105.  
  106.         /* Stuff the foreign socket into the TCB */
  107.         tcb->conn.remote.address = source;
  108.         tcb->conn.remote.port = seg.source;
  109.  
  110.         /* NOW put on right hash chain */
  111.         link_tcb(tcb);
  112.  
  113.         /* Start the timeout on transient state */
  114.         /* This is to prevent TCB's hanging in "SYN Rcvd" state */
  115.         /* when no retour route exists to a calling host */
  116.         start_timer(&tcb->timeout);
  117.     }
  118.     /* Do unsynchronized-state processing (p. 65-68) */
  119.     switch(tcb->state){
  120.     case CLOSED:
  121.         free_p(bp);
  122.         reset(source,dest,tos,length,&seg);
  123.         return;
  124.     case LISTEN:
  125.         if(seg.flags & RST){
  126.             free_p(bp);
  127.             return;
  128.         }
  129.         if(seg.flags & ACK){
  130.             free_p(bp);
  131.             reset(source,dest,tos,length,&seg);
  132.             return;
  133.         }
  134.         if(seg.flags & SYN){
  135.             /* (Security check is bypassed) */
  136.             /* page 66 */
  137.             tcp_stat.conin++;
  138.             proc_syn(tcb,tos,&seg);
  139.             send_syn(tcb);
  140.             setstate(tcb,SYN_RECEIVED);
  141.             if(length != 0 || (seg.flags & FIN)) {
  142.                 break;        /* Continue processing if there's more */
  143.             }
  144.             tcp_output(tcb);
  145.         }
  146.         free_p(bp);    /* Unlikely to get here directly */
  147.         return;
  148.     case SYN_SENT:
  149.         if(seg.flags & ACK){
  150.             if(!seq_within(seg.ack,tcb->iss+1,tcb->snd.nxt)){
  151.                 free_p(bp);
  152.                 reset(source,dest,tos,length,&seg);
  153.                 return;
  154.             }
  155.         }
  156.         if(seg.flags & RST){    /* p 67 */
  157.             if(seg.flags & ACK){
  158.                 /* The ack must be acceptable since we just checked it.
  159.                  * This is how the remote side refuses connect requests.
  160.                  */
  161.                 close_self(tcb,RESET);
  162.             }
  163.             free_p(bp);
  164.             return;
  165.         }
  166.         /* (Security check skipped here) */
  167.         /* Check incoming precedence; it must match if there's an ACK */
  168.         if((seg.flags & ACK) && PREC(tos) != PREC(tcb->tos)){
  169.             free_p(bp);
  170.             reset(source,dest,tos,length,&seg);
  171.             return;
  172.         }
  173.         if(seg.flags & SYN){
  174.             proc_syn(tcb,tos,&seg);
  175.             if(seg.flags & ACK){
  176.                 /* Our SYN has been acked, otherwise the ACK
  177.                  * wouldn't have been valid.
  178.                  */
  179.                 update(tcb,&seg);
  180.                 setstate(tcb,ESTABLISHED);
  181.             } else {
  182.                 setstate(tcb,SYN_RECEIVED);
  183.             }
  184.             if(length != 0 || (seg.flags & FIN)) {
  185.                 break;        /* Continue processing if there's more */
  186.             }
  187.             tcp_output(tcb);
  188.         } else {
  189.             free_p(bp);    /* Ignore if neither SYN or RST is set */
  190.         }
  191.         return;
  192.     }
  193.     /* We reach this point directly in any synchronized state. Note that
  194.      * if we fell through from LISTEN or SYN_SENT processing because of a
  195.      * data-bearing SYN, window trimming and sequence testing "cannot fail".
  196.      */
  197.  
  198.     /* Trim segment to fit receive window. */
  199.     if(trim(tcb,&seg,&bp,&length) == -1){
  200.         /* Segment is unacceptable */
  201.         if(!(seg.flags & RST)){
  202.             tcb->flags |= FORCE;
  203.             tcp_output(tcb);
  204.         }
  205.         return;
  206.     }
  207.     /* If segment isn't the next one expected, and there's data
  208.      * or flags associated with it, put it on the resequencing
  209.      * queue, ACK it and return.
  210.      *
  211.      * Processing the ACK in an out-of-sequence segment without
  212.      * flags or data should be safe, however.
  213.      */
  214.     if(seg.seq != tcb->rcv.nxt
  215.      && (length != 0 || (seg.flags & (SYN|FIN)) )){
  216.         add_reseq(tcb,tos,&seg,bp,length);
  217.         tcb->flags |= FORCE;
  218.         tcp_output(tcb);
  219.         return;
  220.     }
  221.     /* This loop first processes the current segment, and then
  222.      * repeats if it can process the resequencing queue.
  223.      */
  224.     for(;;){
  225.         /* We reach this point with an acceptable segment; all data and flags
  226.          * are in the window, and the starting sequence number equals rcv.nxt
  227.          * (p. 70)
  228.          */
  229.         if(seg.flags & RST){
  230.             if(tcb->state == SYN_RECEIVED
  231.              && !(tcb->flags & (CLONE|ACTIVE))){
  232.                 /* Go back to listen state only if this was
  233.                  * not a cloned or active server TCB
  234.                  */
  235.                 setstate(tcb,LISTEN);
  236.             } else {
  237.                 close_self(tcb,RESET);
  238.             }
  239.             free_p(bp);
  240.             return;
  241.         }
  242.         /* (Security check skipped here) p. 71 */
  243.         /* Check for precedence mismatch or erroneous extra SYN */
  244.         if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){
  245.             free_p(bp);
  246.             reset(source,dest,tos,length,&seg);
  247.             return;
  248.         }
  249.         /* Check ack field p. 72 */
  250.         if(!(seg.flags & ACK)){
  251.             free_p(bp);    /* All segments after synchronization must have ACK */
  252.             return;
  253.         }
  254.         /* Process ACK */
  255.         switch(tcb->state){
  256.         case SYN_RECEIVED:
  257.             if(seq_within(seg.ack,tcb->snd.una+1,tcb->snd.nxt)){
  258.                 update(tcb,&seg);
  259.                 setstate(tcb,ESTABLISHED);
  260.             } else {
  261.                 free_p(bp);
  262.                 reset(source,dest,tos,length,&seg);
  263.                 return;
  264.             }
  265.             break;
  266.         case ESTABLISHED:
  267.         case CLOSE_WAIT:
  268.             update(tcb,&seg);
  269.             break;
  270.         case FINWAIT1:    /* p. 73 */
  271.             update(tcb,&seg);
  272.             if(tcb->sndcnt == 0){
  273.                 /* Our FIN is acknowledged */
  274.                 setstate(tcb,FINWAIT2);
  275.             }
  276.             break;
  277.         case FINWAIT2:
  278.             update(tcb,&seg);
  279.             break;
  280.         case CLOSING:
  281.             update(tcb,&seg);
  282.             if(tcb->sndcnt == 0){
  283.                 /* Our FIN is acknowledged */
  284.                 setstate(tcb,TIME_WAIT);
  285.                 tcb->timer.start = SEC2TICK(MSL2);
  286.                 start_timer(&tcb->timer);
  287.             }
  288.             break;
  289.         case LAST_ACK:
  290.             update(tcb,&seg);
  291.             if(tcb->sndcnt == 0){
  292.                 /* Our FIN is acknowledged, close connection */
  293.                 close_self(tcb,NORMAL);
  294.                 return;
  295.             }
  296. /* I think this is wrong, and can cause permanent ACK-ACK loops.  dmf.
  297.         case TIME_WAIT:
  298.             tcb->flags |= FORCE;
  299.             start_timer(&tcb->timer);
  300. */
  301.         }
  302.  
  303.         /* (URGent bit processing skipped here) */
  304.  
  305.         /* Process the segment text, if any, beginning at rcv.nxt (p. 74) */
  306.         if(length != 0){
  307.             switch(tcb->state){
  308.             case SYN_RECEIVED:
  309.             case ESTABLISHED:
  310.             case FINWAIT1:
  311.             case FINWAIT2:
  312.                 /* Place on receive queue */
  313.                 append(&tcb->rcvq,bp);
  314.                 tcb->rcvcnt += length;
  315.                 tcb->rcv.nxt += length;
  316.                 tcb->rcv.wnd -= length;
  317.                 tcb->flags |= FORCE;
  318.                 break;
  319.             default:
  320.                 /* Ignore segment text */
  321.                 free_p(bp);
  322.                 break;
  323.             }
  324.         }
  325.         /* If the user has set up a r_upcall function and there's
  326.          * data to be read, notify him.
  327.          *
  328.          * This is done before sending an acknowledgement,
  329.          * to give the user a chance to piggyback some reply data.
  330.          * It's also done before processing FIN so that the state
  331.          * change upcall will occur after the user has had a chance
  332.          * to read the last of the incoming data.
  333.          */
  334.         if(tcb->r_upcall && tcb->rcvcnt != 0){
  335.             (*tcb->r_upcall)(tcb,tcb->rcvcnt);
  336.         }
  337.         /* process FIN bit (p 75) */
  338.         if(seg.flags & FIN){
  339.             tcb->flags |= FORCE;    /* Always respond with an ACK */
  340.  
  341.             switch(tcb->state){
  342.             case SYN_RECEIVED:
  343.             case ESTABLISHED:
  344.                 tcb->rcv.nxt++;
  345.                 setstate(tcb,CLOSE_WAIT);
  346.                 break;
  347.             case FINWAIT1:
  348.                 tcb->rcv.nxt++;
  349.                 if(tcb->sndcnt == 0){
  350.                     /* Our FIN has been acked; bypass CLOSING state */
  351.                     setstate(tcb,TIME_WAIT);
  352.                     tcb->timer.start = SEC2TICK(MSL2);
  353.                     start_timer(&tcb->timer);
  354.                 } else {
  355.                     setstate(tcb,CLOSING);
  356.                 }
  357.                 break;
  358.             case FINWAIT2:
  359.                 tcb->rcv.nxt++;
  360.                 setstate(tcb,TIME_WAIT);
  361.                 tcb->timer.start = SEC2TICK(MSL2);
  362.                 start_timer(&tcb->timer);
  363.                 break;
  364.             case CLOSE_WAIT:
  365.             case CLOSING:
  366.             case LAST_ACK:
  367.                 break;        /* Ignore */
  368.             case TIME_WAIT: /* p 76 */
  369.                 start_timer(&tcb->timer);
  370.                 break;
  371.             }
  372.         }
  373.         /* Scan the resequencing queue, looking for a segment we can handle,
  374.          * and freeing all those that are now obsolete.
  375.          */
  376.         while(tcb->reseq != NULLRESEQ && seq_ge(tcb->rcv.nxt,tcb->reseq->seg.seq)){
  377.             get_reseq(tcb,&tos,&seg,&bp,&length);
  378.             if(trim(tcb,&seg,&bp,&length) == 0)
  379.                 goto gotone;
  380.             /* Segment is an old one; trim has freed it */
  381.         }
  382.         break;
  383. gotone: ;
  384.     }
  385.     tcp_output(tcb);    /* Send any necessary ack */
  386. }
  387.  
  388. /* Process an incoming ICMP response */
  389. tcp_icmp(source,dest,type,code,bpp)
  390. int32 source;            /* Original IP datagram source (i.e. us) */
  391. int32 dest;            /* Original IP datagram dest (i.e., them) */
  392. char type,code;            /* ICMP error codes */
  393. struct mbuf **bpp;        /* First 8 bytes of TCP header */
  394. {
  395.     struct tcp seg;
  396.     struct connection conn;
  397.     register struct tcb *tcb;
  398.  
  399.     /* Extract the socket info from the returned TCP header fragment
  400.      * Note that since this is a datagram we sent, the source fields
  401.      * refer to the local side.
  402.      */
  403.     ntohtcp(&seg,bpp);
  404.     conn.local.port = seg.source;
  405.     conn.remote.port = seg.dest;
  406.     conn.local.address = source;
  407.     conn.remote.address = dest;
  408.     if((tcb = lookup_tcb(&conn)) == NULLTCB)
  409.         return; /* Unknown connection, ignore */
  410.  
  411.     /* Verify that the sequence number in the returned segment corresponds
  412.      * to something currently unacknowledged. If not, it can safely
  413.      * be ignored.
  414.      */
  415.     if(!seq_within(seg.seq,tcb->snd.una,tcb->snd.nxt))
  416.         return;
  417.  
  418.     /* The strategy here is that Destination Unreachable and Time Exceeded
  419.      * messages that occur after a connection has been established are likely
  420.      * to be transient events, and shouldn't kill our connection (at least
  421.      * until after we've tried a few more times). On the other hand, if
  422.      * they occur on our very first attempt to send a datagram on a new
  423.      * connection, they're probably "for real". In any event, the info
  424.      * is saved.
  425.      */
  426.     switch(uchar(type)){
  427.     case DEST_UNREACH:
  428.     case TIME_EXCEED:
  429.         tcb->type = type;
  430.         tcb->code = code;
  431.         if(tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED){
  432.             close_self(tcb,NETWORK);
  433.         }
  434.         break;
  435.     case QUENCH:
  436.         /* Source quench; cut the congestion window in half,
  437.          * but don't let it go below one packet
  438.          */
  439.         tcb->cwind /= 2;
  440.         tcb->cwind = max(tcb->mss,tcb->cwind);
  441.         break;
  442.     }
  443. }
  444. /* Send an acceptable reset (RST) response for this segment
  445.  * The RST reply is composed in place on the input segment
  446.  */
  447. static void
  448. reset(source,dest,tos,length,seg)
  449. int32 source;            /* Remote IP address */
  450. int32 dest;            /* Our IP address */
  451. char tos;            /* Type of Service */
  452. int16 length;            /* Length of data portion */
  453. register struct tcp *seg;    /* Offending TCP header */
  454. {
  455.     struct mbuf *hbp;
  456.     struct pseudo_header ph;
  457.     int16 tmp;
  458.     char rflags;
  459.  
  460.     if(seg->flags & RST)
  461.         return; /* Never send an RST in response to an RST */
  462.  
  463.     tcp_stat.resets++;
  464.  
  465.     /* Compose the RST IP pseudo-header, swapping addresses */
  466.     ph.source = dest;
  467.     ph.dest = source;
  468.     ph.protocol = TCP_PTCL;
  469.     ph.length = TCPLEN;
  470.  
  471.     /* Swap port numbers */
  472.     tmp = seg->dest;
  473.     seg->dest = seg->source;
  474.     seg->source = tmp;
  475.  
  476.     rflags = RST;
  477.     if(seg->flags & ACK){
  478.         /* This reset is being sent to clear a half-open connection.
  479.          * Set the sequence number of the RST to the incoming ACK
  480.          * so it will be acceptable.
  481.          */
  482.         seg->seq = seg->ack;
  483.         seg->ack = 0;
  484.     } else {
  485.         /* We're rejecting a connect request (SYN) from LISTEN state
  486.          * so we have to "acknowledge" their SYN.
  487.          */
  488.         rflags |= ACK;
  489.         seg->ack = seg->seq;
  490.         seg->seq = 0;
  491.         if(seg->flags & SYN)
  492.             seg->ack++;
  493.         seg->ack += length;
  494.         if(seg->flags & FIN)
  495.             seg->ack++;
  496.     }
  497.     seg->flags = rflags;
  498.     seg->wnd = 0;
  499.     seg->up = 0;
  500.     seg->mss = 0;
  501.     if((hbp = htontcp(seg,NULLBUF,&ph)) == NULLBUF)
  502.         return;
  503.     /* Ship it out (note swap of addresses) */
  504.     ip_send(dest,source,TCP_PTCL,tos,0,hbp,ph.length,0,0);
  505. }
  506.  
  507. /* Process an incoming acknowledgement and window indication.
  508.  * From page 72.
  509.  */
  510. static void
  511. update(tcb,seg)
  512. register struct tcb *tcb;
  513. register struct tcp *seg;
  514. {
  515.     int16 acked;
  516.     int16 expand;
  517.     int16 window;
  518.  
  519.     acked = 0;
  520.     if(seq_gt(seg->ack,tcb->snd.nxt)){
  521.         tcb->flags |= FORCE;    /* Acks something not yet sent */
  522.         return;
  523.     }
  524.     /* Decide if we need to do a window update.
  525.      * This is always checked whenever a legal ACK is received,
  526.      * even if it doesn't actually acknowledge anything,
  527.      * because it might be a spontaneous window reopening.
  528.      */
  529.     if(seq_gt(seg->seq,tcb->snd.wl1) || ((seg->seq == tcb->snd.wl1)
  530.      && seq_ge(seg->ack,tcb->snd.wl2))){
  531.         /* If the window had been closed, crank back the
  532.          * send pointer so we'll immediately resume transmission.
  533.          * Otherwise we'd have to wait until the next probe.
  534.          */
  535.         if(tcb->snd.wnd == 0 && seg->wnd != 0)
  536.             tcb->snd.ptr = tcb->snd.una;
  537.         tcb->snd.wnd = seg->wnd;
  538.         tcb->snd.wl1 = seg->seq;
  539.         tcb->snd.wl2 = seg->ack;
  540.     }
  541.     /* See if anything new is being acknowledged */
  542.     if(!seq_gt(seg->ack,tcb->snd.una))
  543.         return; /* Nothing more to do */
  544.  
  545.     /* We're here, so the ACK must have actually acked something */
  546.     acked = seg->ack - tcb->snd.una;
  547.  
  548.     /* Expand congestion window if not already at limit */
  549.     if(tcb->cwind < tcb->snd.wnd){
  550.         if(tcb->cwind < tcb->ssthresh){
  551.             /* Still doing slow start/CUTE, expand by amount acked */
  552.             expand = min(acked,tcb->mss);
  553.         } else {
  554.             /* Steady-state test of extra path capacity */
  555.             expand = ((long)tcb->mss * tcb->mss) / tcb->cwind;
  556.         }
  557.         /* Guard against arithmetic overflow */
  558.         if(tcb->cwind + expand < tcb->cwind)
  559.             expand = MAXINT16 - tcb->cwind;
  560.  
  561.         /* Don't expand beyond the offered window */
  562.         if(tcb->cwind + expand > tcb->snd.wnd)
  563.             expand = tcb->snd.wnd - tcb->cwind;
  564.  
  565.         if(expand != 0){
  566. #ifdef    notdef
  567.             /* Kick up the mean deviation estimate to prevent
  568.              * unnecessary retransmission should we already be
  569.              * bandwidth limited
  570.              */
  571.             tcb->mdev += ((long)tcb->srtt * expand) / tcb->cwind;
  572. #endif
  573.             tcb->cwind += expand;
  574.         }
  575.     }
  576.     /* Round trip time estimation */
  577.     if(run_timer(&tcb->rtt_timer) && seq_ge(seg->ack,tcb->rttseq)){
  578.         /* A timed sequence number has been acked */
  579.         stop_timer(&tcb->rtt_timer);
  580.         if(!(tcb->flags & RETRAN)){
  581.             int32 rtt;    /* measured round trip time */
  582.             int32 abserr;    /* abs(rtt - srtt) */
  583.  
  584.             /* This packet was sent only once and now
  585.              * it's been acked, so process the round trip time
  586.              */
  587.             rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
  588.             rtt *= MSPTICK;        /* milliseconds */
  589.  
  590.             /* If this ACKs our SYN, this is the first ACK
  591.              * we've received; base our entire SRTT estimate
  592.              * on it. Otherwise average it in with the prior
  593.              * history, also computing mean deviation.
  594.              */
  595.             if(rtt > tcb->srtt &&
  596.              (tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED)){
  597.                 tcb->srtt = rtt;
  598.             } else {
  599.                 abserr = (rtt > tcb->srtt) ? rtt - tcb->srtt : tcb->srtt - rtt;
  600.                 tcb->srtt = ((AGAIN-1)*tcb->srtt + rtt) / AGAIN;
  601.                 tcb->mdev = ((DGAIN-1)*tcb->mdev + abserr) / DGAIN;
  602.             }
  603.             /* Reset the backoff level */
  604.             tcb->backoff = 0;
  605.         }
  606.     }
  607.     /* If we're waiting for an ack of our SYN, note it and adjust count */
  608.     if(!(tcb->flags & SYNACK)){
  609.         tcb->flags |= SYNACK;
  610.         acked--;
  611.         tcb->sndcnt--;
  612.     }
  613.     /* Remove acknowledged bytes from the send queue and update the
  614.      * unacknowledged pointer. If a FIN is being acked,
  615.      * pullup won't be able to remove it from the queue.
  616.      */
  617.     pullup(&tcb->sndq,NULLCHAR,acked);
  618.  
  619.     /* This will include the FIN if there is one */
  620.     tcb->sndcnt -= acked;
  621.     tcb->snd.una = seg->ack;
  622.  
  623.     /* Stop retransmission timer, but restart it if there is still
  624.      * unacknowledged data.
  625.      */
  626.     stop_timer(&tcb->timer);
  627.     if(tcb->snd.una != tcb->snd.nxt)
  628.         start_timer(&tcb->timer);
  629.  
  630.     /* If retransmissions have been occurring, make sure the
  631.      * send pointer doesn't repeat ancient history
  632.      */
  633.     if(seq_lt(tcb->snd.ptr,tcb->snd.una))
  634.         tcb->snd.ptr = tcb->snd.una;
  635.  
  636.     /* Clear the retransmission flag since the oldest
  637.      * unacknowledged segment (the only one that is ever retransmitted)
  638.      * has now been acked.
  639.      */
  640.     tcb->flags &= ~RETRAN;
  641.  
  642.     /* If outgoing data was acked, notify the user so he can send more
  643.      * unless we've already sent a FIN.
  644.      */
  645.     if(acked != 0 && tcb->t_upcall){
  646.         switch(tcb->state){
  647.         case ESTABLISHED:
  648.         case CLOSE_WAIT:
  649.             window = min(tcb->cwind,tcb->snd.wnd);
  650.             window = min(window,tcb->window);
  651.             window = max(1,window);
  652.             if (tcb->sndcnt < window)
  653.                 (*tcb->t_upcall)(tcb,window - tcb->sndcnt);
  654.         }
  655.     }
  656. }
  657.  
  658. /* Determine if the given sequence number is in our receiver window.
  659.  * NB: must not be used when window is closed!
  660.  */
  661. static
  662. int
  663. in_window(tcb,seq)
  664. struct tcb *tcb;
  665. int32 seq;
  666. {
  667.     return seq_within(seq,tcb->rcv.nxt,(int32)(tcb->rcv.nxt+tcb->rcv.wnd-1));
  668. }
  669.  
  670. /* Process an incoming SYN */
  671. static void
  672. proc_syn(tcb,tos,seg)
  673. register struct tcb *tcb;
  674. char tos;
  675. struct tcp *seg;
  676. {
  677.     int16 mtu,ip_mtu();
  678.  
  679.     tcb->flags |= FORCE;    /* Always send a response */
  680.  
  681.     /* Note: It's not specified in RFC 793, but SND.WL1 and
  682.      * SND.WND are initialized here since it's possible for the
  683.      * window update routine in update() to fail depending on the
  684.      * IRS if they are left unitialized.
  685.      */
  686.     /* Check incoming precedence and increase if higher */
  687.     if(PREC(tos) > PREC(tcb->tos))
  688.         tcb->tos = tos;
  689.     tcb->rcv.nxt = seg->seq + 1;    /* p 68 */
  690.     tcb->snd.wl1 = tcb->irs = seg->seq;
  691.     tcb->snd.wnd = seg->wnd;
  692.     if(seg->mss != 0)
  693.         tcb->mss = seg->mss;
  694.     /* Check the MTU of the interface we'll use to reach this guy
  695.      * and lower the MSS so that unnecessary fragmentation won't occur
  696.      */
  697.     if((mtu = ip_mtu(tcb->conn.remote.address)) != 0){
  698.         /* Allow space for the TCP and IP headers */
  699.         mtu -= TCPLEN + IPLEN;
  700.         tcb->cwind = tcb->mss = min(mtu,tcb->mss);
  701.     }
  702. }
  703.  
  704. /* Generate an initial sequence number and put a SYN on the send queue */
  705. void
  706. send_syn(tcb)
  707. register struct tcb *tcb;
  708. {
  709.     tcb->iss = iss();
  710.     tcb->rttseq = tcb->snd.wl2 = tcb->snd.una = tcb->iss;
  711.     tcb->snd.ptr = tcb->snd.nxt = tcb->rttseq;
  712.     tcb->sndcnt++;
  713.     tcb->flags |= FORCE;
  714. }
  715.  
  716. /* Add an entry to the resequencing queue in the proper place */
  717. static void
  718. add_reseq(tcb,tos,seg,bp,length)
  719. struct tcb *tcb;
  720. char tos;
  721. struct tcp *seg;
  722. struct mbuf *bp;
  723. int16 length;
  724. {
  725.     register struct reseq *rp,*rp1;
  726.  
  727.     /* Allocate reassembly descriptor */
  728.     if((rp = (struct reseq *)malloc(sizeof (struct reseq))) == NULLRESEQ){
  729.         /* No space, toss on floor */
  730.         free_p(bp);
  731.         return;
  732.     }
  733.     ASSIGN(rp->seg,*seg);
  734.     rp->tos = tos;
  735.     rp->bp = bp;
  736.     rp->length = length;
  737.  
  738.     /* Place on reassembly list sorting by starting seq number */
  739.     rp1 = tcb->reseq;
  740.     if(rp1 == NULLRESEQ || seq_lt(seg->seq,rp1->seg.seq)){
  741.         /* Either the list is empty, or we're less than all other
  742.          * entries; insert at beginning.
  743.          */
  744.         rp->next = rp1;
  745.         tcb->reseq = rp;
  746.     } else {
  747.         /* Find the last entry less than us */
  748.         for(;;){
  749.             if(rp1->next == NULLRESEQ || seq_lt(seg->seq,rp1->next->seg.seq)){
  750.                 /* We belong just after this one */
  751.                 rp->next = rp1->next;
  752.                 rp1->next = rp;
  753.                 break;
  754.             }
  755.             rp1 = rp1->next;
  756.         }
  757.     }
  758. }
  759.  
  760. /* Fetch the first entry off the resequencing queue */
  761. static void
  762. get_reseq(tcb,tos,seg,bp,length)
  763. register struct tcb *tcb;
  764. char *tos;
  765. struct tcp *seg;
  766. struct mbuf **bp;
  767. int16 *length;
  768. {
  769.     register struct reseq *rp;
  770.  
  771.     if((rp = tcb->reseq) == NULLRESEQ)
  772.         return;
  773.  
  774.     tcb->reseq = rp->next;
  775.  
  776.     *tos = rp->tos;
  777.     ASSIGN(*seg,rp->seg);
  778.     *bp = rp->bp;
  779.     *length = rp->length;
  780.     free((char *)rp);
  781. }
  782.  
  783. /* Trim segment to fit window. Return 0 if OK, -1 if segment is
  784.  * unacceptable.
  785.  */
  786. static int
  787. trim(tcb,seg,bp,length)
  788. register struct tcb *tcb;
  789. register struct tcp *seg;
  790. struct mbuf **bp;
  791. int16 *length;
  792. {
  793.     struct mbuf *nbp;
  794.     long dupcnt,excess;
  795.     int16 len;        /* Segment length including flags */
  796.     char accept;
  797.  
  798.     accept = 0;
  799.     len = *length;
  800.     if(seg->flags & SYN)
  801.         len++;
  802.     if(seg->flags & FIN)
  803.         len++;
  804.  
  805.     /* Acceptability tests */
  806.     if(tcb->rcv.wnd == 0){
  807.         /* Only in-order, zero-length segments are acceptable when our window
  808.          * is closed.
  809.          */
  810.         if(seg->seq == tcb->rcv.nxt && len == 0){
  811.             return 0;    /* Acceptable, no trimming needed */
  812.         }
  813.     } else {
  814.         /* Some part of the segment must be in the window */
  815.         if(in_window(tcb,seg->seq)){
  816.             accept++;    /* Beginning is */
  817.         } else if(len != 0){
  818.             if(in_window(tcb,(int32)(seg->seq+len-1)) || /* End is */
  819.              seq_within(tcb->rcv.nxt,seg->seq,(int32)(seg->seq+len-1))){ /* Straddles */
  820.                 accept++;
  821.             }
  822.         }
  823.     }
  824.     if(!accept){
  825.         free_p(*bp);
  826.         return -1;
  827.     }
  828.     dupcnt = tcb->rcv.nxt - seg->seq;
  829.     if(dupcnt > 0){
  830.         tcb->rerecv += dupcnt;
  831.         /* Trim off SYN if present */
  832.         if(seg->flags & SYN){
  833.             /* SYN is before first data byte */
  834.             seg->flags &= ~SYN;
  835.             seg->seq++;
  836.             dupcnt--;
  837.         }
  838.         if(dupcnt > 0){
  839.             pullup(bp,NULLCHAR,(int16)dupcnt);
  840.             seg->seq += dupcnt;
  841.             *length -= dupcnt;
  842.         }
  843.     }
  844.     excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
  845.     if(excess > 0){
  846.         tcb->rerecv += excess;
  847.         /* Trim right edge */
  848.         *length -= excess;
  849.         nbp = copy_p(*bp,*length);
  850.         free_p(*bp);
  851.         *bp = nbp;
  852.         seg->flags &= ~FIN;    /* FIN follows last data byte */
  853.     }
  854.     return 0;
  855. }
  856.